// 《围棋》作者版权所有。保留所有权利。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

package json

import (
	"bytes"
	"unicode/utf8"
)

const (
	caseMask     = ^byte(0x20) // ASCII中忽略大小写的掩码。
	kelvin       = '\u212a'
	smallLongEss = '\u017f'
)

// foldFunc返回四个不同大小写折叠等价
// 函数中的一个，从最普通（也是最慢）到最快：
// 
// 1）字节。EqualFold，如果密钥s包含任何非ASCII UTF-8 
// 2）equalFoldRight，如果s包含特殊折叠ASCII（'k'，'k'，'s'，'s'）
// 3）asciiEqualFold，无特殊，但包括非字母（包括）
// 4）SimpleLiterEqualFold，无特殊，无非字母。
// 
// 字母S和K是特殊的，因为它们映射到3个符文，而不仅仅是2：
// /*S映射到S和U+017F'ſ'拉丁文小写字母长S 
// /*K映射到K和U+212A'K' 开尔文符号
// 参见https:
// 
// 返回的函数专门用于与s进行匹配，
// 只应给出s。出于性能原因，不使用该函数。
func foldFunc(s []byte) func(s, t []byte) bool {
	nonLetter := false
	special := false // 特殊字母
	for _, b := range s {
		if b >= utf8.RuneSelf {
			return bytes.EqualFold
		}
		upper := b & caseMask
		if upper < 'A' || upper > 'Z' {
			nonLetter = true
		} else if upper == 'K' || upper == 'S' {
			// 请参见上文了解这些字母的特殊性。
			special = true
		}
	}
	if special {
		return equalFoldRight
	}
	if nonLetter {
		return asciiEqualFold
	}
	return simpleLetterEqualFold
}

// equalFoldRight是字节的特殊化。当s是
// 已知为所有ASCII码（包括标点符号），但包含“s”、
// “s”、“k”或“k”，需要在t中的字节上进行Unicode折叠。
// 参见foldFunc上的注释。
func equalFoldRight(s, t []byte) bool {
	for _, sb := range s {
		if len(t) == 0 {
			return false
		}
		tb := t[0]
		if tb < utf8.RuneSelf {
			if sb != tb {
				sbUpper := sb & caseMask
				if 'A' <= sbUpper && sbUpper <= 'Z' {
					if sbUpper != tb&caseMask {
						return false
					}
				} else {
					return false
				}
			}
			t = t[1:]
			continue
		}
		// sb是ASCII，t不是。t必须是开尔文
		// 符号或长s；sb必须是s、s、k或k。
		tr, size := utf8.DecodeRune(t)
		switch sb {
		case 's', 'S':
			if tr != smallLongEss {
				return false
			}
		case 'k', 'K':
			if tr != kelvin {
				return false
			}
		default:
			return false
		}
		t = t[size:]

	}
	if len(t) > 0 {
		return false
	}
	return true
}

// asciiEqualFold是字节的特殊化。当
// s全部为ASCII（但可能包含非字母）且不包含
// 特殊折叠字母时使用的相等倍。
// 参见foldFunc上的评论。
func asciiEqualFold(s, t []byte) bool {
	if len(s) != len(t) {
		return false
	}
	for i, sb := range s {
		tb := t[i]
		if sb == tb {
			continue
		}
		if ('a' <= sb && sb <= 'z') || ('A' <= sb && sb <= 'Z') {
			if sb&caseMask != tb&caseMask {
				return false
			}
		} else {
			return false
		}
	}
	return true
}

// simpleLetterEqualFold是字节的特殊化。等同于
// 当s是所有ASCII字母（无下划线等）且
// 不包含“k”、“k”、“s”或“s”时使用。
// 参见foldFunc上的评论。
func simpleLetterEqualFold(s, t []byte) bool {
	if len(s) != len(t) {
		return false
	}
	for i, b := range s {
		if b&caseMask != t[i]&caseMask {
			return false
		}
	}
	return true
}
